package cn.iocoder.yudao.module.iot.gateway.service.scene;

import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.iot.core.biz.IotSceneCommonApi;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotSceneGetReqDTO;
import cn.iocoder.yudao.module.iot.core.biz.dto.IotSceneRespDTO;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.List;

import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;

/**
 * IoT 场景信息 Service 实现类
 */
@Service
@Slf4j
public class IotSceneServiceImpl implements IotSceneService {

    private static final Duration CACHE_EXPIRE = Duration.ofMinutes(1);

    /**
     * 通过 id 查询场景的缓存
     */
    private final LoadingCache<Long, IotSceneRespDTO> sceneCaches = buildAsyncReloadingCache(
            CACHE_EXPIRE,
            new CacheLoader<>() {
                @Override
                public IotSceneRespDTO load(Long id) {
                    try {
                        CommonResult<IotSceneRespDTO> result = sceneApi.getScene(new IotSceneGetReqDTO().setId(id));
                        IotSceneRespDTO scene = result.getCheckedData();
                        if (scene != null && scene.getSceneName() != null) {
                            sceneCaches2.put(scene.getSceneName(), scene);
                        }
                        return scene;
                    } catch (Exception e) {
                        log.warn("[load][场景ID:{} 查询失败]", id, e);
                        return null;
                    }
                }
            });

    /**
     * 通过 sceneName 查询场景的缓存
     */
    private final LoadingCache<String, IotSceneRespDTO> sceneCaches2 = buildAsyncReloadingCache(
            CACHE_EXPIRE,
            new CacheLoader<>() {
                @Override
                public IotSceneRespDTO load(String sceneName) {
                    try {
                        CommonResult<IotSceneRespDTO> result = sceneApi.getScene(new IotSceneGetReqDTO().setSceneName(sceneName));
                        IotSceneRespDTO scene = result.getCheckedData();
                        if (scene != null && scene.getId() != null) {
                            sceneCaches.put(scene.getId(), scene);
                        }
                        return scene;
                    } catch (Exception e) {
                        log.warn("[load][场景名称:{} 查询失败]", sceneName, e);
                        return null;
                    }
                }
            });

    @Resource
    private IotSceneCommonApi sceneApi;

    @Override
    public IotSceneRespDTO getSceneFromCache(Long id) {
        try {
            return sceneCaches.getUnchecked(id);
        } catch (Exception e) {
            log.warn("[getSceneFromCache][场景ID:{} 获取失败]", id, e);
            return null;
        }
    }

    @Override
    public IotSceneRespDTO getSceneFromCache(String sceneName) {
        try {
            return sceneCaches2.getUnchecked(sceneName);
        } catch (Exception e) {
            log.warn("[getSceneFromCache][场景名称:{} 获取失败]", sceneName, e);
            return null;
        }
    }

    @Override
    public List<IotSceneRespDTO> getAllScenes() {
        CommonResult<List<IotSceneRespDTO>> result = sceneApi.getAllScenes(null);
        return result.getCheckedData();
    }

    @Override
    public List<IotSceneRespDTO> getSceneActionsByDeviceId(Long deviceId) {
        CommonResult<List<IotSceneRespDTO>> result = sceneApi.getSceneActionsByDeviceId(deviceId);
        return result.getCheckedData();
    }

    @Override
    public List<IotSceneRespDTO> getScenesAndActionsByDeviceId(Long deviceId) {
        CommonResult<List<IotSceneRespDTO>> result = sceneApi.getSceneActionsByDeviceId(deviceId);
        return result.getCheckedData();
    }

    @Override
    public List<IotSceneRespDTO> getAllEnabledScenes() {
        CommonResult<List<IotSceneRespDTO>> result = sceneApi.getAllEnabledScenes();
        return result.getCheckedData();
    }
}